package com.iwdnb.gkgz.common.quota;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.alibaba.fastjson.JSONObject;

import com.iwdnb.gkgz.common.model.dto.StockDayData;
import com.iwdnb.gkgz.common.utils.BigDecimalUtils;
import lombok.Data;

public class BollingerBands {

    /**
     * 计算简单移动平均数
     */
    private static double simpleMovingAverage(double[] values) {
        double sum = 0.0;
        for (double v : values) {
            sum += v;
        }
        return sum / values.length;
    }

    /**
     * 计算标准差
     */
    private static double standardDeviation(double[] values, double average) {
        double sum = 0.0;
        for (double v : values) {
            sum += Math.pow(v - average, 2);
        }
        return Math.sqrt(sum / values.length);
    }

    public static List<BollingerData> calculateBollingerBands(List<StockDayData> stockDayDataList) {
        return calculateBollingerBands(stockDayDataList, 20, 2);
    }

    /**
     * 计算布林线
     */
    public static List<BollingerData> calculateBollingerBands(List<StockDayData> stockDayDataList, int period, int k) {
        double[] prices = new double[stockDayDataList.size()];
        String[] dates = new String[stockDayDataList.size()];

        for (int i = 0; i < stockDayDataList.size(); i++) {
            prices[i] = stockDayDataList.get(i).getClosePrice().doubleValue();
            dates[i] = stockDayDataList.get(i).getDate();
        }
        List<BollingerData> bollingerDataList = calculateBollingerBands(dates, prices, period, k);
        for (int i = period - 1; i < prices.length; i++) {
            StockDayData stockDayData = stockDayDataList.get(i);
            BollingerData bollingerData = bollingerDataList.get(i - period + 1);
            stockDayData.setBollingerBand(bollingerData);
        }
        return bollingerDataList;
    }

    /**
     * 计算布林线
     */
    public static List<BollingerData> calculateBollingerBands(String[] dates, double[] prices, int period, int k) {
        List<BollingerData> bollingerDataList = new ArrayList<>();
        for (int i = period - 1; i < prices.length; i++) {
            // 提取N周期内的股价数据
            double[] window = Arrays.copyOfRange(prices, i - period + 1, i + 1);

            // 计算中轨
            double sma = simpleMovingAverage(window);

            // 计算标准差
            double sd = standardDeviation(window, sma);

            // 计算上轨和下轨
            double upperBand = sma + k * sd;
            double lowerBand = sma - k * sd;
            BollingerData data = new BollingerData();
            data.setMiddleBand(BigDecimalUtils.of(sma));
            data.setHighBand(BigDecimalUtils.of(upperBand));
            data.setLowBand(BigDecimalUtils.of(lowerBand));
            data.setDate(dates[i]);
            bollingerDataList.add(data);
        }
        return bollingerDataList;
    }

    @Data
    public static class BollingerData {
        private String date;
        private BigDecimal middleBand;
        private BigDecimal highBand;
        private BigDecimal lowBand;
    }

    public static void main(String[] args) {
        String[] dates = {
            // 这里应该是实际的股票日期
        };
        double[] prices = {
            // 这里应该是实际的股票收盘价数据
        };

        // 假设我们使用20天作为周期，2作为标准差倍数
        int period = 20;
        int k = 2;

        calculateBollingerBands(dates, prices, period, k);
    }

}

